package org.theta.framework.cloud.trace;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.annotation.Order;
import org.theta.framework.core.lang.AppException;

import brave.ScopedSpan;
import brave.Tracer;

@Aspect
@Order(-98)
@ConfigurationProperties(prefix = "nrxt.sleuth")
public class SleuthTraceInterceptor {

	@Autowired
	private Tracer tracer;

	@Around(value = "within(@org.theta.framework.core.trace.ServiceTrace *)")
	public Object invoke(ProceedingJoinPoint pjp) throws Throwable {
		if (tracer == null)
			return pjp.proceed(pjp.getArgs());
		Method method = ((MethodSignature) pjp.getSignature()).getMethod();
		Object target = pjp.getTarget();
		Object result = null;
		String methodName = target.getClass().getSimpleName() + "." + method.getName();

		final ScopedSpan span = tracer.startScopedSpan(methodName);
		span.annotate("Local invoke begin.");
		span.tag("Class-Name", target.getClass().getSimpleName());
		span.tag("Method-Name", method.getName());
		try {
			result = pjp.proceed(pjp.getArgs());
		} catch (AppException appEx) {
			span.error(appEx);
		} catch (Throwable t) {
			span.error(t);
		} finally {
			span.annotate("Local invoke end.");
			span.finish();
		}
		return result;
	}
}
